﻿Imports System
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.Workflow.ComponentModel

Namespace System.Workflow.Runtime
    Public NotInheritable Class WorkflowInstance
        ' Methods
        Friend Sub New(ByVal instanceId As Guid, ByVal workflowRuntime As WorkflowRuntime)
            If (instanceId = Guid.Empty) Then
                Throw New ArgumentException(String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.CantBeEmptyGuid, New Object() { "instanceId" }))
            End If
            If (workflowRuntime Is Nothing) Then
                Throw New ArgumentNullException("workflowRuntime")
            End If
            Me._instanceId = instanceId
            Me._runtime = workflowRuntime
        End Sub

        Public Sub Abort()
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                If (executor.WorkflowStatus = WorkflowStatus.Created) Then
                    Throw New InvalidOperationException(ExecutionStringManager.CannotAbortBeforeStart)
                End If
                Try 
                    executor.Abort
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Sub ApplyWorkflowChanges(ByVal workflowChanges As WorkflowChanges)
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                Try 
                    executor.ApplyWorkflowChanges(workflowChanges)
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Sub EnqueueItem(ByVal queueName As IComparable, ByVal item As Object, ByVal pendingWork As IPendingWork, ByVal workItem As Object)
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                executor = Me._runtime.Load(Me)
                Try 
                    executor.EnqueueItem(queueName, item, pendingWork, workItem)
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Sub EnqueueItemOnIdle(ByVal queueName As IComparable, ByVal item As Object, ByVal pendingWork As IPendingWork, ByVal workItem As Object)
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                Try 
                    executor.EnqueueItemOnIdle(queueName, item, pendingWork, workItem)
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            Dim instance As WorkflowInstance = [TryCast](obj,WorkflowInstance)
            If (instance Is Nothing) Then
                Return False
            End If
            Return (Me._instanceId = instance._instanceId)
        End Function

        Public Overrides Function GetHashCode() As Integer
            Return Me._instanceId.GetHashCode
        End Function

        Public Function GetWorkflowDefinition() As Activity
            Dim executor As WorkflowExecutor
            Dim workflowDefinitionClone As Activity
        Label_0000:
            Do
                executor = Me._runtime.Load(Me)
            Loop While Not executor.IsInstanceValid
            Try 
                workflowDefinitionClone = executor.GetWorkflowDefinitionClone("")
            Catch exception1 As InvalidOperationException
                If executor.IsInstanceValid Then
                    Throw
                End If
                goto Label_0000
            End Try
            Return workflowDefinitionClone
        End Function

        Public Function GetWorkflowNextTimerExpiration() As DateTime
            Dim executor As WorkflowExecutor
            Dim workflowNextTimerExpiration As DateTime
        Label_0000:
            Do
                executor = Me._runtime.Load(Me)
            Loop While Not executor.IsInstanceValid
            Try 
                workflowNextTimerExpiration = executor.GetWorkflowNextTimerExpiration
            Catch exception1 As InvalidOperationException
                If executor.IsInstanceValid Then
                    Throw
                End If
                goto Label_0000
            End Try
            Return workflowNextTimerExpiration
        End Function

        Public Function GetWorkflowQueueData() As ReadOnlyCollection([Of] WorkflowQueueInfo)
            Dim executor As WorkflowExecutor
            Dim workflowQueueInfos As ReadOnlyCollection([Of] WorkflowQueueInfo)
            If (Not Me._deadWorkflow Is Nothing) Then
                Return Me._deadWorkflow.GetWorkflowQueueInfos
            End If
        Label_0014:
            Do
                executor = Me._runtime.Load(Me)
            Loop While Not executor.IsInstanceValid
            Try 
                workflowQueueInfos = executor.GetWorkflowQueueInfos
            Catch exception1 As InvalidOperationException
                If executor.IsInstanceValid Then
                    Throw
                End If
                goto Label_0014
            End Try
            Return workflowQueueInfos
        End Function

        Friend Function GetWorkflowResourceUNSAFE() As WorkflowExecutor
            Dim executor As WorkflowExecutor
            Dim executor2 As WorkflowExecutor
        Label_0000:
            Do
                executor = Me._runtime.Load(Me)
            Loop While Not executor.IsInstanceValid
            Try 
                executor2 = executor
            Catch exception1 As InvalidOperationException
                If executor.IsInstanceValid Then
                    Throw
                End If
                goto Label_0000
            End Try
            Return executor2
        End Function

        Public Sub Load()
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Me._runtime.Load(Me)
            End [Using]
        End Sub

        Friend Sub ProcessTimers()
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Nothing
                    Try 
                        executor = Me._runtime.Load(Me)
                    Catch exception1 As InvalidOperationException
                        Return
                    End Try
                Loop While ((executor Is Nothing) OrElse Not executor.IsInstanceValid)
                Try 
                    executor.DeliverTimerSubscriptions
                Catch exception2 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Friend Sub ProcessTimers(ByVal ignored As Object)
            Me.ProcessTimers
        End Sub

        Public Sub ReloadTrackingProfiles()
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                Try 
                    Me._runtime.TrackingListenerFactory.ReloadProfiles(executor)
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Sub [Resume]()
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                Try 
                    executor.Resume
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Sub Start()
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                Try 
                    executor.Start
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Sub Suspend(ByVal [error] As String)
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                If (executor.WorkflowStatus = WorkflowStatus.Created) Then
                    Throw New InvalidOperationException(ExecutionStringManager.CannotSuspendBeforeStart)
                End If
                Try 
                    executor.Suspend([error])
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                Catch exception As ExecutorLocksHeldException
                    Try 
                        exception.Handle.WaitOne
                    Catch exception3 As ObjectDisposedException
                    End Try
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Sub Terminate(ByVal [error] As String)
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
            Label_000C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                Try 
                    executor.Terminate([error])
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_000C
                End Try
            End [Using]
        End Sub

        Public Function TryUnload() As Boolean
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor = Me._runtime.Load(Me)
                [Using] executor.ExecutorLock.Enter
                    If executor.IsInstanceValid Then
                        Try 
                            Return executor.TryUnload
                        Catch exception1 As InvalidOperationException
                            If executor.IsInstanceValid Then
                                Throw
                            End If
                        End Try
                    End If
                End [Using]
                Return False
            End [Using]
        End Function

        Public Sub Unload()
            [Using] New WorkflowTraceTransfer(Me.InstanceId)
                Dim executor As WorkflowExecutor
                If ((Me._runtime Is Nothing) OrElse (Me._runtime.GetService([Of] WorkflowPersistenceService) Is Nothing)) Then
                    Throw New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.MissingPersistenceService, New Object() { Me.InstanceId }))
                End If
            Label_004C:
                Do
                    executor = Me._runtime.Load(Me)
                Loop While Not executor.IsInstanceValid
                Try 
                    executor.Unload
                Catch exception1 As InvalidOperationException
                    If executor.IsInstanceValid Then
                        Throw
                    End If
                    goto Label_004C
                Catch exception As ExecutorLocksHeldException
                    Try 
                        exception.Handle.WaitOne
                    Catch exception3 As ObjectDisposedException
                    End Try
                    goto Label_004C
                End Try
            End [Using]
        End Sub


        ' Properties
        Friend WriteOnly Property DeadWorkflow As WorkflowExecutor
            Set(ByVal value As WorkflowExecutor)
                Me._deadWorkflow = value
            End Set
        End Property

        Public ReadOnly Property InstanceId As Guid
            Get
                Return Me._instanceId
            End Get
        End Property

        Public ReadOnly Property WorkflowRuntime As WorkflowRuntime
            Get
                Return Me._runtime
            End Get
        End Property


        ' Fields
        Private _deadWorkflow As WorkflowExecutor
        Private _instanceId As Guid
        Private _runtime As WorkflowRuntime
    End Class
End Namespace

